#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
垃圾代码生成器
生成看似有用但实际无用的代码文件，增加逆向难度
"""

import os
import random
import string
from pathlib import Path
from typing import List, Dict, Optional

from core.builtin_config_module.builtin_config import BuiltInConfig
from core.utils_module.language_utils import detect_language_for_file
from core.utils_module.logger import ObfuscationLogger


class DummyCodeGenerator:
    """垃圾代码生成器"""

    # 复杂度配置
    COMPLEXITY_CONFIG = {
        'low': {
            'methods': 2,
            'properties': 2,
            'max_depth': 1,
            'add_inheritance': False,
            'add_protocols': False
        },
        'medium': {
            'methods': 5,
            'properties': 4,
            'max_depth': 2,
            'add_inheritance': True,
            'add_protocols': False
        },
        'high': {
            'methods': 10,
            'properties': 8,
            'max_depth': 3,
            'add_inheritance': True,
            'add_protocols': True
        }
    }

    def __init__(self, config: BuiltInConfig, logger: ObfuscationLogger):
        """
        初始化垃圾代码生成器

        Args:
            config: 统一配置对象
            logger: 日志记录器
        """
        self.config = config
        self.logger = logger
        self.generated_count = 0
        self.generated_files = []

    def generate_for_project(self, project_path: str,
                            count: Optional[int] = None,
                            complexity: Optional[str] = None) -> bool:
        """
        为项目生成垃圾代码

        Args:
            project_path: 项目路径
            count: 生成数量（优先使用此参数，否则使用配置）
            complexity: 复杂度 low/medium/high（优先使用此参数）

        Returns:
            是否成功
        """
        start_count = self.generated_count

        try:
            # 使用参数或配置
            count = count or self.config.advanced_features.dummy_code_count
            complexity = complexity or self.config.advanced_features.dummy_code_complexity

            self.logger.log_operation(
                "垃圾代码生成",
                f"开始生成 {count} 个文件，复杂度: {complexity}"
            )

            # 检测项目语言
            languages = self._detect_project_languages(project_path)

            if not languages:
                self.logger.log_warning("未检测到支持的语言，默认使用 Swift")
                languages = ['swift']

            self.logger.log_operation("语言检测", f"检测到语言: {', '.join(languages)}")

            # 为每种语言生成垃圾代码
            self.generated_files = []

            files_per_language = count // len(languages)
            remainder = count % len(languages)

            for i, lang in enumerate(languages):
                lang_count = files_per_language + (1 if i < remainder else 0)

                if lang == 'swift':
                    self._generate_swift_dummy(project_path, lang_count, complexity)
                elif lang == 'objc':
                    self._generate_objc_dummy(project_path, lang_count, complexity)
                elif lang == 'java':
                    self._generate_java_dummy(project_path, lang_count, complexity)
                elif lang == 'kotlin':
                    self._generate_kotlin_dummy(project_path, lang_count, complexity)

            generated_this_run = self.generated_count - start_count

            self.logger.log_operation(
                "垃圾代码生成完成",
                f"成功生成 {generated_this_run} 个文件"
            )

            return True

        except Exception as e:
            self.generated_count = start_count
            self.logger.log_error(f"垃圾代码生成失败: {e}")
            return False

    def _detect_project_languages(self, project_path: str) -> List[str]:
        """
        检测项目使用的编程语言

        Args:
            project_path: 项目路径

        Returns:
            语言列表
        """
        detected = set()

        for root, _, files in os.walk(project_path):
            # 跳过隐藏目录和构建目录
            if any(part.startswith('.') or part in ['build', 'dist', '__pycache__']
                  for part in Path(root).parts):
                continue

            for file in files:
                language = detect_language_for_file(file)
                if language:
                    detected.add(language)

        return list(detected)

    def _generate_swift_dummy(self, project_path: str, count: int, complexity: str):
        """
        生成 Swift 垃圾代码

        Args:
            project_path: 项目路径
            count: 生成数量
            complexity: 复杂度
        """
        dummy_dir = os.path.join(project_path, 'DummyCode')
        os.makedirs(dummy_dir, exist_ok=True)

        config = self.COMPLEXITY_CONFIG[complexity]

        for i in range(count):
            class_name = f"Dummy{self._random_string(8)}"

            # 构建类定义
            inheritance = ""
            if config['add_inheritance'] and random.random() > 0.5:
                base_class = random.choice(['NSObject', 'Equatable', 'Hashable'])
                inheritance = f": {base_class}"

            protocols = ""
            if config['add_protocols'] and random.random() > 0.5:
                protocol_list = random.sample(['Codable', 'CustomStringConvertible'],
                                             k=random.randint(1, 2))
                protocols = ", " + ", ".join(protocol_list) if inheritance else ": " + ", ".join(protocol_list)

            # 生成属性
            properties = []
            for j in range(config['properties']):
                prop_type = random.choice(['String', 'Int', 'Double', 'Bool', '[String]', '[Int: String]'])
                prop_name = f"property{j+1}"
                prop_value = self._generate_swift_value(prop_type)
                properties.append(f"    private var {prop_name}: {prop_type} = {prop_value}")

            # 生成方法
            methods = []
            for j in range(config['methods']):
                method = self._generate_swift_method(j+1, config['max_depth'])
                methods.append(method)

            # 组装类
            content = f"""
import Foundation

class {class_name}{inheritance}{protocols} {{
{chr(10).join(properties)}

{chr(10).join(methods)}
}}
"""

            file_path = os.path.join(dummy_dir, f"{class_name}.swift")
            with open(file_path, 'w', encoding='utf-8') as f:
                f.write(content)

            self.generated_count += 1
            self.generated_files.append(file_path)
            self.logger.log_file_processing(file_path, "已生成")

    def _generate_swift_method(self, index: int, max_depth: int) -> str:
        """生成 Swift 方法"""
        method_name = f"method{index}"
        return_type = random.choice(['String', 'Int', 'Bool', 'Void'])

        if return_type == 'Void':
            return_stmt = ""
        else:
            return_value = self._generate_swift_value(return_type)
            return_stmt = f"\n        return {return_value}"

        # 添加一些复杂逻辑
        body_lines = []
        if max_depth > 1:
            body_lines.append("        let temp = [1, 2, 3].map { $0 * 2 }")
        if max_depth > 2:
            body_lines.append("        let filtered = temp.filter { $0 > 2 }")
            body_lines.append(f"        let _ = \"{self._random_string(20)}\"")

        body = "\n".join(body_lines) if body_lines else "        // Dummy operation"

        return f"""    func {method_name}() -> {return_type} {{
{body}{return_stmt}
    }}"""

    def _generate_swift_value(self, swift_type: str) -> str:
        """生成 Swift 类型的值"""
        if swift_type == 'String':
            return f'"{self._random_string(random.randint(5, 20))}"'
        elif swift_type == 'Int':
            return str(random.randint(1, 1000))
        elif swift_type == 'Double':
            return str(round(random.uniform(1.0, 100.0), 2))
        elif swift_type == 'Bool':
            return random.choice(['true', 'false'])
        elif swift_type == '[String]':
            return f'["{self._random_string(5)}", "{self._random_string(5)}"]'
        elif swift_type == '[Int: String]':
            return f'[{random.randint(1, 10)}: "{self._random_string(5)}"]'
        return '""'

    def _generate_java_dummy(self, project_path: str, count: int, complexity: str):
        """生成 Java 垃圾代码"""
        dummy_dir = os.path.join(project_path, 'dummy')
        os.makedirs(dummy_dir, exist_ok=True)

        config = self.COMPLEXITY_CONFIG[complexity]

        for i in range(count):
            class_name = f"Dummy{self._random_string(8)}"

            # 生成属性
            fields = []
            for j in range(config['properties']):
                field_type = random.choice(['String', 'int', 'double', 'boolean'])
                field_name = f"field{j+1}"
                field_value = self._generate_java_value(field_type)
                fields.append(f"    private {field_type} {field_name} = {field_value};")

            # 生成方法
            methods = []
            for j in range(config['methods']):
                method = self._generate_java_method(j+1, config['max_depth'])
                methods.append(method)

            content = f"""
package dummy;

public class {class_name} {{
{chr(10).join(fields)}

{chr(10).join(methods)}
}}
"""

            file_path = os.path.join(dummy_dir, f"{class_name}.java")
            with open(file_path, 'w', encoding='utf-8') as f:
                f.write(content)

            self.generated_count += 1
            self.generated_files.append(file_path)
            self.logger.log_file_processing(file_path, "已生成")

    def _generate_java_method(self, index: int, max_depth: int) -> str:
        """生成 Java 方法"""
        method_name = f"method{index}"
        return_type = random.choice(['String', 'int', 'boolean', 'void'])

        if return_type == 'void':
            return_stmt = ""
        else:
            return_value = self._generate_java_value(return_type)
            return_stmt = f"\n        return {return_value};"

        body = "        // Dummy operation"
        if max_depth > 1:
            body = f'        String unused = "{self._random_string(20)}";'

        return f"""    public {return_type} {method_name}() {{
{body}{return_stmt}
    }}"""

    def _generate_java_value(self, java_type: str) -> str:
        """生成 Java 类型的值"""
        if java_type == 'String':
            return f'"{self._random_string(random.randint(5, 20))}"'
        elif java_type == 'int':
            return str(random.randint(1, 1000))
        elif java_type == 'double':
            return str(round(random.uniform(1.0, 100.0), 2))
        elif java_type == 'boolean':
            return random.choice(['true', 'false'])
        return '""'

    def _generate_kotlin_dummy(self, project_path: str, count: int, complexity: str):
        """生成 Kotlin 垃圾代码"""
        dummy_dir = os.path.join(project_path, 'dummy')
        os.makedirs(dummy_dir, exist_ok=True)

        config = self.COMPLEXITY_CONFIG[complexity]

        for i in range(count):
            class_name = f"Dummy{self._random_string(8)}"

            # 生成属性
            properties = []
            for j in range(config['properties']):
                prop_type = random.choice(['String', 'Int', 'Double', 'Boolean'])
                prop_name = f"property{j+1}"
                prop_value = self._generate_kotlin_value(prop_type)
                properties.append(f"    private val {prop_name}: {prop_type} = {prop_value}")

            # 生成方法
            methods = []
            for j in range(config['methods']):
                method = self._generate_kotlin_method(j+1)
                methods.append(method)

            content = f"""
package dummy

class {class_name} {{
{chr(10).join(properties)}

{chr(10).join(methods)}
}}
"""

            file_path = os.path.join(dummy_dir, f"{class_name}.kt")
            with open(file_path, 'w', encoding='utf-8') as f:
                f.write(content)

            self.generated_count += 1
            self.generated_files.append(file_path)
            self.logger.log_file_processing(file_path, "已生成")

    def _generate_kotlin_method(self, index: int) -> str:
        """生成 Kotlin 方法"""
        method_name = f"method{index}"
        return_type = random.choice(['String', 'Int', 'Boolean', 'Unit'])

        if return_type == 'Unit':
            return_stmt = ""
        else:
            return_value = self._generate_kotlin_value(return_type)
            return_stmt = f"\n        return {return_value}"

        return f"""    fun {method_name}(): {return_type} {{
        val unused = "{self._random_string(20)}"{return_stmt}
    }}"""

    def _generate_kotlin_value(self, kotlin_type: str) -> str:
        """生成 Kotlin 类型的值"""
        if kotlin_type == 'String':
            return f'"{self._random_string(random.randint(5, 20))}"'
        elif kotlin_type == 'Int':
            return str(random.randint(1, 1000))
        elif kotlin_type == 'Double':
            return str(round(random.uniform(1.0, 100.0), 2))
        elif kotlin_type == 'Boolean':
            return random.choice(['true', 'false'])
        return '""'

    def _generate_objc_dummy(self, project_path: str, count: int, complexity: str):
        """生成 Objective-C 垃圾代码"""
        dummy_dir = os.path.join(project_path, 'DummyCode')
        os.makedirs(dummy_dir, exist_ok=True)

        config = self.COMPLEXITY_CONFIG[complexity]

        for i in range(count):
            class_name = f"Dummy{self._random_string(8)}"

            # .h 文件
            header_content = f"""
#import <Foundation/Foundation.h>

@interface {class_name} : NSObject

@property (nonatomic, strong) NSString *property1;
@property (nonatomic, assign) NSInteger property2;

- (NSString *)method1;
- (NSInteger)method2:(NSInteger)param;

@end
"""

            # .m 文件
            impl_content = f"""
#import "{class_name}.h"

@implementation {class_name}

- (instancetype)init {{
    self = [super init];
    if (self) {{
        self.property1 = @"{self._random_string(20)}";
        self.property2 = {random.randint(1, 1000)};
    }}
    return self;
}}

- (NSString *)method1 {{
    return [NSString stringWithFormat:@"%@%ld", self.property1, (long)self.property2];
}}

- (NSInteger)method2:(NSInteger)param {{
    return param * self.property2;
}}

- (void)unusedMethod {{
    NSString *unused = @"{self._random_string(50)}";
}}

@end
"""

            header_path = os.path.join(dummy_dir, f"{class_name}.h")
            impl_path = os.path.join(dummy_dir, f"{class_name}.m")

            with open(header_path, 'w', encoding='utf-8') as f:
                f.write(header_content)
            with open(impl_path, 'w', encoding='utf-8') as f:
                f.write(impl_content)

            self.generated_count += 2  # .h 和 .m
            self.generated_files.extend([header_path, impl_path])
            self.logger.log_file_processing(header_path, "已生成")
            self.logger.log_file_processing(impl_path, "已生成")

    def _random_string(self, length: int) -> str:
        """生成随机字符串"""
        return ''.join(random.choices(string.ascii_letters + string.digits, k=length))

    def get_statistics(self) -> dict:
        """获取生成统计"""
        return {
            'generated_count': self.generated_count,
            'generated_files': self.generated_files
        }
